אשמח אם תסתכל:
http://hacking.org.il/showthread.php?t=2906
4 תשובות
השאלה שלך הייתה איך לגרום לזה שלחיצה כפולה על submit לא תכניס את אותה שורה למסד פעמיים.
באופן כללי נתנו לך את הפתרון הנכון - צריך לשמור את הזמן שבו נשלחה הבקשה ולבדוק שזמן הבקשה הבא הוא אחרי זמן מסוים ולא מיד.
הבעיה היא זה איפה לשמור את הנתונים האלה. יש לסשן תחונה מיוחדת, הנתונים בה נשמרים רק בסוף הסקריפט, ככה שהיא אפשר לשמור נתונים בסשן בתוך סקריפט שעדיין רץ ככה שסקריפט מקביל אליו יקרא אותם.
האפשרויות שלך
או לא להשתמש בשביל זה בסשן, אלה במסד נתונים כלשהו, כמו memcached, redis
או לעקוף מגבלה זו על ידי כך שתצטרך לגרום לסקריפט לרשום את הסשן כמה שיותר מוקדם לזכרון באמצעות הפונקציה session_write_close בערך בצורה הבאה:
if(!isset($_SESSION['lastsentry'])) $_SESSION['lastsentry'] = time();
else
{
if($_SESSION['lastsentry'] + 5) die();
else $_SESSION['lastsentry'] = time();
}
session_write_close();
// ... long long script
באמת, זה כל הכלים?
לא. אם אתה חושב שאתה ממש צריך להגביל את אפשרות השליחה של הטופס - תוסיף גם קפצ'ה והגבלה לפי IP, אבל ברוב המקרים אתה לא באמת צריך את כל אלה, ו disable פשוט לכפתור יפתור לך את הבעיה.
הוספתי הגבלה עם ip ומסד נתונים
תסתכל בפורום בתגובות למטה יותר.
הבעיה היא ששולחים המון בקשות לשרת בו זמנית, על ידי לחיצה על הכפתור מספר רב של פעמים מהר.
מה שקורה הוא שכל הבקשות לשרת רצות באותו זמן, וברגע שלחצת פעם אחת על הכפתור קוד ה-php מתחיל לרוץ, וכשהוא מגיע לחלק שמוסיף שורה למסד עם הip, הבקשה השנייה שנשלחה לשרת פועלת באותו זמן, ולכן נוצרים כפיליות של שורות עם אותו ip.
מבין?
אם שולחים לך 100 בקשות באותה מילי שניה אתה לא יכול לעשות אם זה שום דבר כי הם עוד לא הגיעו לקוד שלך בכלל. כתיבה אחת למסד של לשמור IP בתחילת הסקריפט היא לא כזו איטית, אבל אתה צודק, זה גובל בחוסר אפשרות לעשות בכלל משהו.
אתה יכול גם לשלוח לגוגל 100 בקשות חיפוש במקביל. אין משהו שאפשר לעשות אם זה למעט לרשום ממי הגיע, מתי ומה התוכן וכל פעם להשוות את זה. ויש כמה דרכים לממש את ההצעה:
לרשום בסשן (שגם לא ישלחו לך בקשות בלי קוקי ולא יעזור), במסד לפי IP (שזה הדרך הכי טובה)
או ברמת השרת, לכתוב איזה מודול, ששומר ב memcache רשימה של תוכן טופס, זמן ו IP וכל פעם בודק אם כבר נשלח כזה. אם כן, אפילו לא מעביר את הפעולה למפענח ה PHP.
השאלה היא רק באיזה שלב אתה מציב את המגבלה ועד כמה שווה לשים אותה שם.
ברמת השרת - יתפוס הכי מוקדם, אבל הכי קשה לממש.
ברמת הקוד - יתפוס מאוחר, אבל ניתן למימוש בצורה פשוטה.
למה לסבך דברים ולא להשתמש בשיטה של Post/Redirect/Get?